
/***************************************************************************
													object.cpp  -  description
														 -------------------
		begin                : Tue Aug 27 2002
		copyright            : (C) 2002 by Michiel Visser
		email                : 
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "expr.h"
#include "parser.h"
#include "mstl.h"

using namespace Expression;

namespace Sess
{

int StructIndex::update()
{		
	TypeVar s(session.getCurType());
	if (!!s)
	{	if ((char *)(s->m_elems[m_index].m_name) != (char *)m_name)
		{	m_index = s->findElem(m_name);
			if (m_index<0) 
			{	return 1;
			}
		}
		session.m_curTypePtr = s->m_elems[m_index].m_typeVarPtr;
		return 0;
	}
	return 2;
}

TypeVar RegExpResultType;

void LocalVarVectorQueue::pop()
{	if (m_varCount) 
	{ Vector<VarValue> &v=*m_stack;
		for(int j=v.length();--j>=0;)
		{	v.decLengthWithoutDestroy(); // this makes it safe against garbage collection
			v[j].~VarValue();
		}
		m_stack.removeone();	
	}
}
#if 0
void LocalVarVectorQueue::indexCopy(int i, void *space)
{ if (!m_stack) new (space) NullObject(); else { (*m_stack)[i].m_value->duplicateIn(space); }
}
#endif
static bool s_fl = false;

bool operator==(const String &c, const StructElem &s) { return s.m_name==c; }
bool operator==(const String &c, const TypeVar &s) { return s->m_name==c; }

StructElem::StructElem(String name, TypeVar t): m_name(name)
{
	new (m_typeVarPtr) TypeVar(t);
}

static Object *containArray(OList &ol, int mylevel, int parentlevel)
{ Object *o=NEW_OBJ ListObject(ol);
	if (mylevel>parentlevel)
	{
		OList pol;
		pol.prepend(NEW_OBJ StringObject(" )"));
		pol.prepend(o);
		pol.prepend(NEW_OBJ StringObject("( "));
		return NEW_OBJ ListObject(pol);
	}
	return o;
}
Object *bracketize(Object *o)
{
	OList pol;
	pol.prepend(NEW_OBJ StringObject(" ]"));
	pol.prepend(o);
	pol.prepend(NEW_OBJ StringObject("[ "));
	return NEW_OBJ ListObject(pol);	
}

bool TypeFunc::assignsToTypeIdentifier(const TypeVal *type) const { return false; }
bool TypeFunc::assignsToStructElement(TypeVar parent, int elem) const { return false; }
bool TypeSelection::assignsToTypeIdentifier(const TypeVal *type) const { return type==(TypeVal *)m_type; }
bool TypeAssignment::assignsToTypeIdentifier(const TypeVal *type) const { return m_l->assignsToTypeIdentifier(type); }
bool TypeToStructElemAssignment::assignsToStructElement(TypeVar parent, int elem) const { return parent==m_parent && elem==m_elem; }
bool PreTypeSelection::assignsToTypeIdentifier(const TypeVal *type) const { return type->m_name==m_typeName; }

enum
{
	levelTypeLiteral, // a, a.b, :a
	levelTypeAssignment,
	levelTypeStructConcat,
	levelType
};
Object *TypeAssignment::toArrayObject(int parentlevel, List<TypeFunc>::P &funcs) const
{
	OList arr;
	OList::P array(&arr);
	ADDA(m_l->toArrayObject(levelTypeLiteral, funcs));
	ADDSTR(" = ");
	ADDA(m_r->toArrayObject(levelType, funcs));
	return containArray(arr,levelType,parentlevel);
}
Object *TypeSelection::toArrayObject(int parentlevel, List<TypeFunc>::P &funcs) const
{
	return m_type->toArrayObject(parentlevel, funcs);
}
Object *PreTypeSelection::toArrayObject(int parentlevel, List<TypeFunc>::P &funcs) const
{
	OList arr;
	OList::P array(&arr);
	ADDSTR(m_typeName);
	return containArray(arr,levelTypeLiteral,parentlevel);;
}

Object *StructIndexing::toArrayObject(int parentlevel, List<TypeFunc>::P &funcs) const
{
	OList arr;
	OList::P array(&arr);
	ADDA(m_type->toArrayObject(levelTypeLiteral, funcs));
	ADDSTR(".");
	ADDSTR(m_index.m_name);
	return containArray(arr,levelTypeLiteral,parentlevel);
}
Object *StructConcat::toArrayObject(int parentlevel, List<TypeFunc>::P &funcs) const
{
	OList arr;
	OList::P array(&arr);
	ADDA(m_l->toArrayObject(levelTypeStructConcat, funcs)); //todo, parentlevel check?
	ADDSTR(" + ");
	ADDA(m_r->toArrayObject(levelTypeAssignment, funcs));
	return containArray(arr,levelTypeStructConcat,parentlevel);
}

Object *TypeToStructElemAssignment::toArrayObject(int parentlevel, List<TypeFunc>::P &funcs) const
{
	return m_subFunc->toArrayObject(parentlevel,funcs);
}

Object *TypeVal::elemsToArrayObject(const List<TypeFunc> &funcs) const
{
	OList arr;
	OList::P array(&arr);
	List<TypeFunc>::P pfs(&funcs); 
	elemsToArray(array,pfs);
	return NEW_OBJ ListObject(arr);
}


void TypeVal::elemsToArray(OList::P &array, List<TypeFunc>::P &funcs) const
{
	int l=m_elems.length(),i=0;
	if (l)
		for(;;)
		{	if (!!*funcs && (*funcs)->assignsToStructElement(TypeVar(this), i))
			{	TypeFunc &f=**funcs;
				funcs++;
				ADDA(bracketize(f.toArrayObject(levelType,funcs)));
			}
			else if (!!*m_elems[i].m_typeVarPtr)
					ADDA(bracketize((*m_elems[i].m_typeVarPtr)->toArrayObject(levelType,funcs)));
			ADDSTR(m_elems[i].m_name);
			i++;
			if (i==l)
				break;
			ADDSTR(", ");
		}
	if (m_isDynamic)
		ADDSTR(", ...");
}

Object *TypeVal::toArrayObject(int parentlevel, List<TypeFunc>::P &funcs) const
{
	OList arr;
	OList::P array(&arr);
	if (!!m_name)
	{
		if (!!*funcs && (*funcs)->assignsToTypeIdentifier(this))
		{	TypeFunc &f=**funcs;
			funcs++;
			ADDA(f.toArrayObject(parentlevel,funcs));
		}
		else
			ADDSTR(m_name);
	}
	else if (isMap())
	{
		TypeVar key (*m_elems[0].m_typeVarPtr);
		if (!!key)
		{	ADDA(key->toArrayObject(levelTypeStructConcat,funcs));
		}
		else if (!!*funcs && (*funcs)->assignsToStructElement(TypeVar(this), 0))
		{	TypeFunc &f=**funcs;
			funcs++;
			ADDA(f.toArrayObject(levelTypeStructConcat,funcs));
		}
		ADDSTR(" => ");
		if (!!m_childType)
		{	ADDA(m_childType->toArrayObject(levelType,funcs));
		}
		else if (!!*funcs && (*funcs)->assignsToStructElement(TypeVar(this), -1))
		{	TypeFunc &f=**funcs;
			funcs++;
			ADDA(f.toArrayObject(levelType,funcs));
		}
		return containArray(arr,levelType,parentlevel);
	}
	else if (!!m_childType)
	{	ADDSTR(": ");
		ADDA(m_childType->toArrayObject(levelType, funcs));
	}
	else if (!!*funcs && (*funcs)->assignsToStructElement(TypeVar(this), -1))
	{	ADDSTR(": ");
		TypeFunc &f=**funcs;
		funcs++;
		ADDA(f.toArrayObject(levelType,funcs));
	}
	else
	{	ADDSTR("{ ");
		elemsToArray(array,funcs);
		ADDSTR(" }");
	}
	return NEW_OBJ ListObject(arr);
}

void TypeVal::getElemNames(OList &o)
{
	int i;
	for(i=m_elems.length(); --i>=0;)
		o.prepend(NEW_OBJ StringObject(m_elems[i].m_name));
}

TypeVar TypeSelection::evaluate(bool &once)
{ once=false;
	return m_type;
}

TypeVar PreTypeSelection::evaluate(bool &once)
{ // do not set once to false in this situation!
	TypeVar p(session.findType(m_typeName));
	if (!p)
	{ p = session.newTypeEntry(m_typeName);
	}
	this->~PreTypeSelection();
	new (this) TypeSelection(p);
	return p;
}

Object *TypeFunc::toArrayObject(int parentlevel, List<TypeFunc>::P &funcs) const { return 0; }

TypeVar TypeAssignment::evaluate(bool &once)
{	once=false;
	TypeVar lv(m_l->evaluate());
	if (!lv) return TypeVar();
	TypeVar rv(m_r->evaluate());
	if (!!rv)
	{	lv->set(*rv);	
	}
	return lv;
}

TypeVar StructConcat::evaluate(bool &once)
{	once=false;
	TypeVar lv(m_l->evaluate());
	TypeVar rv(m_r->evaluate());
	if (!lv) return rv;
	if (!rv) return lv;
	TypeVar res;
	new (res) TypeVal(*lv,*rv);
	return res;
}

TypeVar StructIndexing::evaluate(bool &once)
{ once=false;
	TypeVar t(m_type->evaluate());
	if (!t)
		return TypeVar();
	int i = m_index.m_index;
	if ((char *)t->m_elems[i].m_name != (char *)m_index.m_name)
	{ 
		i=t->findElem(m_index.m_name);
		if (i<0) 
		{ session.reportRuntimeError(String("Cannot find element '")+m_index.m_name+"' in a TypeVal.");
			return TypeVar(); //error
		}
		m_index.m_index=i;
	}
	return *t->m_elems[i].m_typeVarPtr;
}

TypeVar TypeVal::getCopy(TypeVal *from)
{	
	if (!!from)
	{	if(from->isAnonymous())
		{ TypeVar ns;
			new (ns) TypeVal(*from);
			return ns;
		}
		return TypeVar(from);
	}
	return TypeVar();
}
TypeVal::TypeVal( TypeVar key, TypeVar childType) : m_isDynamic(false), m_isSystem(false), m_childType(childType), m_elems(1) 
{ new (m_elems.space(0)) StructElem(String(),key);
}
void TypeVal::set(const List<StructElem> &elems, bool isDynamic)
{	
	Vector<StructElem> v(elems.length());
	m_elems.take(v);
	m_isDynamic = isDynamic;
	int j=0;
	FOREACH(List<StructElem>, elems, e)
	{	new (m_elems.space(j++)) StructElem(e->m_name,*e->m_typeVarPtr); // do not use getCopy or else "?[{[{[a.b]c}]d}]" will go wrong
	}
}

void TypeVal::set(const TypeVal &s)
{ 
	int lc;
	Vector<StructElem> v(lc=s.m_elems.length());
	m_elems.take(v);
	m_isDynamic = s.m_isDynamic; 
	while(--lc>=0)
	{	StructElem &e=s.m_elems[lc];
		new (m_elems.space(lc)) StructElem(e.m_name, getCopy(*e.m_typeVarPtr));
	}
	m_childType = getCopy(s.m_childType);
}

TypeVal::TypeVal(const TypeVal &left,const TypeVal &right): m_isDynamic(right.m_isDynamic),m_isSystem(false), m_elems(left.m_elems.length()+right.m_elems.length())
{
	// todo: check childs are empty 
	int rc=right.m_elems.length();
	int lc=left.m_elems.length();
	while(--rc>=0)
	{	StructElem &e=right.m_elems[rc];
		new (m_elems.space(rc+lc)) StructElem(e.m_name, getCopy(*e.m_typeVarPtr));
	}
	while(--lc>=0)
	{	StructElem &e=left.m_elems[lc];
		new (m_elems.space(lc)) StructElem(e.m_name, getCopy(*e.m_typeVarPtr));
	}
}

int TypeVal::findElem(String m)
{ int index=m_elems.findIndex(m);
	if (index>=0) 
	{	m_elems[index].m_name=m; //this makes sure the fast compare (pointer compare) works. // TODO: if ptr<ptr2 ptr=ptr2...!
		return index;
	}
	if (!m_isDynamic)
		return -1;
	int i=m_elems.length();
	m_elems.growByRealloc(i+1);
	new (m_elems.space(i)) StructElem(m,TypeVar());
	return i;
}

void Session::addFunc(EPtr e)
{	m_global.insertVar(e->toTyle(),NEW_OBJ ExprObject(e));
}

void Session::init()
{
	m_firstStackVar.val=NullObject::obj();
	m_mainThread=m_curThread=new Thread();
	//if (s_fl)		logPrintf("Tyle session started.\n");
	EPtr e;
#define FUNC_EXPR(x) 	new (e) x##Expr(); addFunc(e);
#include "funcs.h"
	{	m_global.insertVar("tyleVersion",NEW_OBJ StringObject(TYLE_VERSION));
	}
	NEW_CONSTEXPR(m_exprNull) NullObject();
	NEW_CONSTEXPR(m_exprEmptyList) ListObject();
	NEW_CONSTEXPR(m_exprEmptyMap) MapObject();
	NEW_CONSTEXPR(m_iteratorVarExpr) IteratorVarExpr();
	NEW_CONSTEXPR(m_iteratorKeyVarExpr) IteratorKeyVarExpr();
	{	
		int i,j;
		for(i=0;i<4;i++) {
			NEW_CONSTEXPR(m_exprNumbers[i]) IntegerObject(i);
			new (m_argumentListExprs[i]) ArgumentListExpr(i);
			for(j=0;j<2;j++)
				new (m_argumentExprs[i][j]) ArgumentExpr(j,i);
		}
	}
	TypeVar sub;
	new (sub) TypeVal();
	List<StructElem> ses; // from last to first:
	new (ses.prependalloc()) StructElem("regs", sub);
	new (ses.prependalloc()) StructElem("len", sub);
	new (ses.prependalloc()) StructElem("pos", sub);
	TypeVar p;
	(new (p) TypeVal())->set(ses,false);
	new (RegExpResultType) TypeVal(p);
	sub->setSystem();
	p->setSystem();
	RegExpResultType->setSystem();
}

void Session::quit() 
{
	enterLite();
	m_global.erase();
	m_firstStackVar.set(0);
	m_types.erase();
	_ASSERT(!m_execStack);
	_ASSERT(!m_curScope);
	FOREACH(ThreadList, m_threads, i) i->erase();	
	leave();
}

void Session::enter()
{ 
	m_execCs.enter();
	if (!m_curThread || !m_curThread->isCurrent()) {
		if(m_curThread) {
			m_curThread->m_curScope=m_curScope;
			m_curThread->m_execStack.take(m_execStack);
			m_curThread->m_stack.take(m_stack);
			m_curThread->m_curClosures = m_curClosures;
			m_curThread->m_curTypePtr = m_curTypePtr;
			memcpy(m_curThread->m_firstPainters, m_firstPainters, sizeof(m_firstPainters));
		}
		m_curThread=*m_threads.finddata(Thread::getCurId());
		m_curScope = m_curThread->m_curScope;
		m_execStack.take(m_curThread->m_execStack);
		m_stack.take(m_curThread->m_stack);
		m_curClosures = m_curThread->m_curClosures;
		m_curTypePtr = m_curThread->m_curTypePtr;
		memcpy(m_firstPainters, m_curThread->m_firstPainters, sizeof(m_firstPainters));
		m_curThread->clearFirstPainters();
	}
}
void Session::execPushLvvq(LocalVarVectorQueue::Ptr q)
{	((LocalVarVectorQueue &)*q).push();
	execPush(q);
}
void Session::execPopLvvq()
{	((LocalVarVectorQueue &)*m_curScope).pop();
	execPop();
}
void Session::fillPointerMap(const Object *root)
{
	session.m_pointerMapNextIndex=0; 
	root->fillPointerMap(); // register all references.
	root->fillPointerCounts();
	PointerMap::iterator i;
	for(i=session.m_pointerMap.begin(); i!=session.m_pointerMap.end();) {
		//printf("%i->%i,",i->first->getTypeNum(),i->second.m_count);
		if (i->second.m_count<=1)
			session.m_pointerMap.erase(i++);
		else
			i++;
	}
}
void Session::clearPointerMap()
{
	session.m_pointerMap.clear(); 
}

void Session::reportRuntimeError(String str)
{ EPtr v=m_global.findVar("reportRuntimeError");
	if (!!v)
	{ pushStack(NEW_OBJ StringObject(str));
		{
			Object::HolderCP ovh;
	 	 	v->evaluateToCopy(ovh);
			ovh.protectChilds();
			ovh->evaluateToVoid();
		}
		popStack();
	}
}

void fileLogging(bool fl)
{
	s_fl=fl;
	if (fl)
	{	FILE *f;
		f=fopen("tylelog.txt","w");
		fclose(f);
	}
}

void logPrintf(const char *format, ...)
{
	FILE *f;
	if (s_fl) f=fopen("tylelog.txt","a");
	va_list va;
	va_start(va, format);
	if (s_fl) vfprintf(f, format, va);
	//if (dump       )   vprintf(   format, va);
	va_end(va);
	if (s_fl) fclose(f);
}

/*void GlobalVarVector::dumpVars()
{	for(int i=0; i<e_hashSize;i++)
	{	FOREACH(List<GlobalVariable>,hash[i],j)
			logPrintf(false,"%s ",(char *)j->getName());
		if (!!(hash[i])) logPrintf(false,",");
	}
	logPrintf(false,"\n");
}*/

void Session::stackString(const char *str, int len)
{	//m_mainThread->setToCurrent();
	enterFromAnyThread();
	{
		Object *r;
		if (len>=0)
			r=NEW_OBJ StringObject(str,len);
		else
			r=NEW_OBJ StringObject(str);
		m_firstStackVar.set(r);
	}
	leave();
}

ExternObject *Session::evaluateToCopy(const unsigned char *pos) 
{	
	ExternObject *result;
	m_evalCs.enter();
	
	enterFromAnyThread();
	{
		selectGlobal();
		EPtr res;
		if (s_fl) 
			logPrintf("Evaluating: %s ... ", pos);
		ExternObject::MyList l;
		Object *space=l.prepend();
		TyleParser(pos, res, space); 
		if (!!res) {
			res->evaluateToPersistCopy(space);
			m_firstStackVar.set(space->copy());
		}
		result=attachFirstExtern(l);
#ifdef MALLOC_COUNT
		_TVAR(i,mcounts.variable)
		_TVAR(i,mcounts.block)
		_TVAR(i,mcounts.deletionCandidate)
#endif
		if (s_fl) 
			logPrintf(" Done.\n");
	}
	leave();
	m_evalCs.leave();
	return result;
}; 

ExternObject *Session::attachFirstExtern(ExternObject::MyList &from)
{	
	Sess::Session::m_externObjects.takeprependone(from);
	ExternObject *first=&*m_externObjects;
	ExternObject *pn=(first->m_holder=&m_externObjects)->pnext();
	if (pn) pn->m_holder = &first->m_holder->next();
	return first;
}

EPtr Scope::insertVar(String s, bool localFind) { _ASSERT(0); return EPtr(); }
bool Scope::isEmpty() const { return false; }

bool LocalVarVectorQueue::isEmpty() const { return m_varCount==0; }

EPtr NamedIteratorVarsScope::findVar(String s, bool localFind)
{
	if (s==m_name)
	{	EPtr res;
		new (res) NamedIteratorVarExpr(session.m_funcLevel-m_depth,NamedIteratorVarsScope::Ptr(this));
		return res;
	}
	if (s==m_keyName)
	{	EPtr res;
		new (res) NamedIteratorKeyVarExpr(session.m_funcLevel-m_depth+1,NamedIteratorVarsScope::Ptr(this));
		return res;
	}
	return EPtr();
}

EPtr ParamListScope::findVar(String s, bool localFind)
{
	int i=m_type->findElem(s);
	if (i>=0)
	{	EPtr res;
		new (res) ParamExpr(m_type->m_elems[i].m_name,session.m_funcLevel);
		return res;
	}
	return EPtr();
}

void Session::schedule()    { leave(); enter(); }

EPtr Session::findOrInsert(String s, bool localFind) //todo: dollar
{ Scope *i;
	for(i=m_curScope; i; )
	{ EPtr e ( i->findVar(s, localFind) );
		if (!!e) return e;
		if (localFind && m_curScope->isEmpty())
			return m_curScope->insertVar(s, localFind);
		i=i->m_father;
	}
	return m_global.getVarExpression(s);
}

void ThreadVars::GCPaint()
{ 
	FOREACH(List<StackVar>, m_stack, i) session.GCPaintObject(i->val);
	{	for(Painter *p=m_firstPainters[0];p;p=p->m_next)
		{	const Object *o=((SelfPainter *)p)->m_obj;
			if (o) session.GCPaintObject(o);
		}
	}
	{	for(Painter *p=m_firstPainters[1];p;p=p->m_next)
		{	const Object *o=((ChildrenPainter *)p)->m_obj;
			if (o) o->GCPaintMyChildren();
		}
	}
	{	for(Painter *p=m_firstPainters[2];p;p=p->m_next)
		{	FOREACH(OList, ((OListChildrenPainter *)p)->m_obj, i)
			{	session.GCPaintObject(*i);
			}
		}
	}
	if (!!m_curScope)
	{ Scope *p=m_curScope;
		FOREACH(List<Scope::Ptr>, m_execStack,j)
		{ p->GCPaint();
			p=*j;
		}
	}
}

void Scope::GCPaint() {}

void Thread::GCPaint()
{ 
	FOREACH(List<Object>,m_incoming,i)
	{	i->GCPaintMyChildren();
	}
	if (!!m_func)
		m_func->GCPaintMyChildren();
	ThreadVars::GCPaint();
}

void Session::GCPaint()
{ 
	if (m_firstStackVar.val) GCPaintObject(m_firstStackVar.val);
	//if (m_flow.resultSpace) GCPaintObject(m_flow.resultSpace);
	ThreadVars::GCPaint();
	m_global.GCPaint();
	FOREACH(ThreadList, m_threads,j) (*j)->GCPaint(); // it does not matter than curThread is done as well.
	while(!!m_childrenPaintStack)
	{	const Object *o = *m_childrenPaintStack;
		m_childrenPaintStack.removeone();
		o->GCPaintMyChildren();
	}
	FOREACH(ExternObject::MyList, m_externObjects, i) (*i)->GCPaintMyChildren();
	_ASSERT(m_sharedLiteralObjects.length()==0);//todo: ook de sharedLiteral doen?
}

Session session;

void LocalVarVectorQueue::GCPaint()
{
	FOREACH(List< Vector<VarValue> >, m_stack, i)
	{ VarValue *l=(VarValue *)*i;
		for(int j=i->length();--j>=0;)
		{ session.GCPaintObject(l[j].m_value);
		}
	}
}
void GlobalVarVector::GCPaint()
{
	List<GlobalVariable> *ls = hash.getLists();
	
	for(int i=hash.size; --i>=0; )
	{	FOREACH(List<GlobalVariable>, ls[i], j)
		{	session.GCPaintObject(j->m_value);
		}
	}
}
void GlobalVarVector::erase()
{
	List<GlobalVariable> *ls = hash.getLists();	
	for(int i=hash.size; --i>=0; )
	{	ls[i].erase();
	}
	new (m_names) MapObject(); //TODO: is m_names correctly deleted?
}

void LocalVarVectorQueue::push()
{
	if (m_varCount) {
		/*VarValue *l = (VarValue *)*(new (m_stack) Vector<VarValue>(m_varCount));
		for(int count=m_varCount; --count>=0;)
		{ new (l+count) VarValue();
		}
		*/
		(new (m_stack) Vector<VarValue>(m_varCount))->init();
		/*for(int count=m_varCount; --count>=0;)
		{ _ASSERT(&*((*m_stack)[count].m_value));
		}*/
	}
}

EPtr LocalVarVectorQueue::findVar(String s, bool localFind)
{	int i=vars.findindex(s);
	if (i>=0) {
		if (localFind) {
			EPtr res;
			LocalVarVectorQueue::Ptr p(this);
			new (res) LocalBlockVarExpr(p,i);
			return res;
		}
		else
			return vars[i].expr; // todo: improve speed
	}
	return EPtr();
}

ClosureBinding::ClosureBinding(EPtr to, ClosureScope::Ptr scope): m_expr(to), m_scope(scope),
	m_vars(((ClosureScope &)*m_scope).m_count)
{
	int j=0;
	FOREACH(List<Closure>, ((ClosureScope &)*m_scope).m_closures, i) {
		Object *o=i->expr->evaluateToOriginal();
		new (m_vars.space(j++)) VarValue(o, TypeVarPtr(session.m_curTypePtr));	
	}
}

EPtr ClosureScope::findVar(String s, bool localFind)
{
	Closure *e=m_closures.finddata(s);
	if (e) {
		return e->m_intern;
	}
	int oldLevel=session.m_funcLevel;
	session.m_funcLevel=m_depth;
	EPtr r;
	for(Scope *i=m_father; i; i=i->m_father ) {
		EPtr e = i->findVar(s, localFind);
		if (!!e)
			{	new (r) ClosureVarExpr(m_count++);
				new (m_closures.end()) Closure( s, e, r);
				break;
			}
	}
	session.m_funcLevel=oldLevel;
	return r;
}

EPtr LocalVarVectorQueue::insertVar(String s, bool localFind)
{
	EPtr res;
	LocalVarVectorQueue::Ptr p(this);
	int vi=vars.length();
 	Variable *v=new (vars.end()) Variable(s);
 	new (res) BlockVarExpr(p,vi);
	v->expr = res;
 	if (localFind)
		new (res) LocalBlockVarExpr(p,vi);
	return res;
}

GlobalVariable *GlobalVarVector::registerVar(String name, Object *v) 
{	
	insertName( name );
	return new (hash.getList(name)) GlobalVariable(name, v);
}

EPtr GlobalVarVector::findVar(String s)
{	
	GlobalVariable *sv=hash.find(s);
	if (sv)
	{ return sv->expr;
	}
	else return EPtr();
}

EPtr GlobalVarVector::getVarExpression(String s)
{
	EPtr res = findVar(s);
	if (!!res) return res;
	new (res) GlobalVarInitialExpr(s);
	return res;
}

void GlobalVarVector::insertVar(String s, Object *r)
{
 	GlobalVariable *v=registerVar(s,r);
	EPtr e;
	new (e) GlobalVarExpr(*v);
 	v->expr = e;
}

#ifdef __WIN__
Thread::Thread(): m_id(GetCurrentThreadId()), 
#else
Thread::Thread(): m_thread(getCurId()),
#endif
	m_father(0), m_func(0)
{
	//m_prio=GetThreadPriority(m_thread); // GetCurrentThread()
	session.m_threads.prepend(this);
}
Thread::Thread(Thread *father, Object *func): m_father(father), m_func(func), m_sem(true)
{
	//DuplicateHandle(GetCurrentProcess(),handle,GetCurrentProcess(),&pseudoHandle,0,FALSE,DUPLICATE_SAME_ACCESS);
	session.m_threads.prepend(this);
}
#ifdef __WIN__
void Thread::setVars(HANDLE me, DWORD threadId)
{	m_id = threadId;
	m_prio=GetThreadPriority(me);
}
#endif
Thread::~Thread()
{ //CloseHandle(pseudoHandle);
	session.m_threads.find(this).removeone();
}

ClosureScope::~ClosureScope() {}
NamedIteratorVarsScope::~NamedIteratorVarsScope() {}
//ParamScope::~ParamScope() {}
Scope::~Scope() {}
ParamListScope::~ParamListScope() {}
LocalVarVectorQueue::~LocalVarVectorQueue() {}

#ifdef DEBUGLOGGING

void Session::doLog(Expr *expr)
{
	new (m_logQueue.put()) EPtr(expr);
}
void Session::getLog(void *space)
{
	OList ll;
	session.m_annotate=true;
	for(int i=m_logQueue.count(); --i>=0;)
	{
		ll.prepend(m_logQueue[i]->toArrayObject());
	}
	session.m_annotate=false;
	new (space) ListObject(ll);
}

#endif

TypeVar TypeToStructElemAssignment::evaluate(bool &once)
{
	once = true; // this must be set back to false when not preTypeSelection
	if (m_elem<0)
	{ 
		return m_parent->m_childType = m_subFunc->evaluate();
	}
	else
		return *m_parent->m_elems[m_elem].m_typeVarPtr = m_subFunc->evaluate();
}

TypeFunc::~TypeFunc() {}
TypeToStructElemAssignment::~TypeToStructElemAssignment	() {}
TypeAssignment::~TypeAssignment() {}
TypeSelection::~TypeSelection() {}
StructIndexing::~StructIndexing() {}
StructConcat::~StructConcat() {}
PreTypeSelection::~PreTypeSelection() {}
}
